#ifndef QUERY_BUILDER_H
#define QUERY_BUILDER_H
#include "predicates.h"
#include "query_executor.h"
#include <memory>

namespace abc_query
{

    class QueryBuilder
    {
    public:
        explicit QueryBuilder()
            : predicate_(nullptr) {}

        // 节点类型过滤
        QueryBuilder &nodeType(abc::AbcNodeType type)
        {
            addPredicate(std::make_shared<NodeTypePredicate>(type));
            return *this;
        }

        // 模块过滤
        QueryBuilder &module(const std::string &module)
        {
            addPredicate(std::make_shared<ModulePredicate>(module));
            return *this;
        }

        // package过滤
        QueryBuilder &package(const std::string &pkg)
        {
            addPredicate(std::make_shared<PackagePredicate>(pkg));
            return *this;
        }

        // 函数名过滤
        QueryBuilder &functionName(const std::string &pattern)
        {
            addPredicate(std::make_shared<FunctionNamePredicate>(pattern));
            return *this;
        }

        // 谓词组合
        QueryBuilder &And(const QueryBuilder &other)
        {
            if (other.predicate_)
            {
                predicate_ = std::make_shared<AndPredicate>(predicate_, other.predicate_);
            }
            return *this;
        }

        QueryBuilder &Or(const QueryBuilder &other)
        {
            if (other.predicate_)
            {
                predicate_ = std::make_shared<OrPredicate>(predicate_, other.predicate_);
            }
            return *this;
        }

        // 执行查询
        std::vector<abc::AbcNodePtr> findNodes(const abc::AbcArchive::Ptr &archive) const
        {
            if (!predicate_)
                return {};
            return QueryExecutor::findNodes(archive, predicate_);
        }

        std::vector<abc::AbcFunctionPtr> findFunctions(const abc::AbcArchive::Ptr &archive) const
        {
            if (!predicate_)
                return {};
            return QueryExecutor::findFunctions(archive, predicate_);
        }

    private:
        void addPredicate(std::shared_ptr<Predicate> predicate)
        {
            if (!predicate_)
            {
                predicate_ = predicate;
            }
            else
            {
                predicate_ = std::make_shared<AndPredicate>(predicate_, predicate);
            }
        }

        std::shared_ptr<Predicate> predicate_;
    };
}

#endif
